/* 
 * File:   misc.h
 * Author: filipp
 *
 * Created on March 15, 2010, 4:34 PM
 */

#ifndef _MISC_H
#define	_MISC_H

#include <math.h>
#include <vector>
#include <algorithm>

typedef unsigned char byte;

template <typename T>
class autoInitPtr{
public:
	autoInitPtr() : ptr(NULL) {}
	autoInitPtr(T* p) : ptr(p) {}
	autoInitPtr(const autoInitPtr<T>& aipt) : ptr(aipt.ptr) {}
	autoInitPtr<T>& operator=(const autoInitPtr<T>& aipt) { ptr=aipt.ptr; }
	T* ptr;
};
template <typename T>
T& operator*(const autoInitPtr<T>& aipt){ return *aipt.ptr; }
template <typename T>
autoInitPtr<T>& operator+=(autoInitPtr<T>& aipt, int i) { aipt.ptr+=i; return aipt; }
template <typename T>
autoInitPtr<T>& operator-=(autoInitPtr<T>& aipt, int i) { aipt.ptr-=i; return aipt; }
template <typename T>
autoInitPtr<T> operator+(const autoInitPtr<T>& aipt, int i) { return aipt.ptr + i; }
template <typename T>
autoInitPtr<T> operator-(const autoInitPtr<T>& aipt, int i) { return aipt.ptr - i; }
template <typename T>
int operator-(const autoInitPtr<T>& l, const autoInitPtr<T>& r) { return l.ptr-r.ptr; }

template <typename T>
class smoothTracer{
public:
	smoothTracer(size_t smoothness) : data(new T[smoothness]), s(smoothness),
		c(0) {
		for(size_t i=0; i<s; ++i)
			data[i]=0;
	}
	void nextValue(const T& value){
		data[c++]=value;
		if(c>=s)
			c=0;
	}
	T average(){
		T accum=0;
		for(size_t i=0; i<s; ++i)
			accum+=data[i];
		accum/=s;
		return accum;
	}
private:
	T* data;
	size_t s;
	size_t c;
};

class statisticTracker{
public:
	statisticTracker(size_t dataSize=1);
	void resize(size_t dataSize);
	void addData(float point);
	void doCalculations(bool a=false);		//WARNING: TAKES A WHILE, ONLY DO ONCE PER FRAME
	void doCalculations(float* extData, size_t s, bool a=false); //perform calculations on external data
	float linearTransform(float point) const;
	float normalTransform(float point) const;
	float absoluteTransform(float point) const;
	float minimum() const;
	float maximum() const;
	float average() const;
	float deviation() const;
private:
	float mu;
	float var;
	float stdev;
	float stdev_2;
	float max_val;
	float min_val;
	float div_range;
	size_t size;
	size_t index;
	float* data;
};

enum UserEventType{
	USER_NO_EVENT=0,
	USER_SCREEN_REFRESH_REQUEST,
	USER_GAME_REFRESH_REQUEST
};

class vec2f;

class vec2i{
public:
	vec2i(int nx=0, int ny=0);
	vec2i(const vec2i& other);
	vec2i(const vec2f& other);
	vec2i& operator=(const vec2i& other);
	vec2i& operator=(const vec2f& other);
	int dot(const vec2i& r) const;
	int cross(const vec2i& r) const;
	float magnitude() const;
	vec2f normalized() const;
	int x;
	int y;
};
vec2i& operator+=(vec2i& l, const vec2i& r);
vec2i& operator-=(vec2i& l, const vec2i& r);
vec2i& operator*=(vec2i& l, const vec2i& r);
vec2i& operator/=(vec2i& l, const vec2i& r);
vec2i& operator*=(vec2i& l, int r);
vec2i& operator/=(vec2i& l, int r);
vec2i& operator*=(vec2i& l, float r);
vec2i& operator/=(vec2i& l, float r);
vec2i& operator<<=(vec2i& l, int r);
vec2i& operator>>=(vec2i& l, int r);
vec2i operator+(const vec2i& l, const vec2i& r);
vec2i operator-(const vec2i& l, const vec2i& r);
vec2i operator*(const vec2i& l, const vec2i& r);
vec2i operator/(const vec2i& l, const vec2i& r);
vec2i operator*(const vec2i& l, int r);
vec2i operator/(const vec2i& l, int r);
vec2i operator*(const vec2i& l, float r);
vec2i operator/(const vec2i& l, float r);
vec2i operator<<(const vec2i& l, int r);
vec2i operator>>(const vec2i& l, int r);
vec2i operator*(int l, const vec2i& r);
vec2i operator-(const vec2i& r);
bool operator==(const vec2i& l, const vec2i& r);
bool operator!=(const vec2i& l, const vec2i& r);


class vec2f{
public:
	vec2f(float nx=0, float ny=0);
	vec2f(const vec2f& other);
	vec2f(const vec2i& other);
	vec2f& operator=(const vec2f& other);
	vec2f& operator=(const vec2i& other);
	float dot(const vec2f& r) const;
	float cross(const vec2f& r) const;
	float magnitude() const;
	vec2f normalized() const;
	float x;
	float y;
};
vec2f& operator+=(vec2f& l, const vec2f& r);
vec2f& operator-=(vec2f& l, const vec2f& r);
vec2f& operator*=(vec2f& l, const vec2f& r);
vec2f& operator/=(vec2f& l, const vec2f& r);
vec2f& operator*=(vec2f& l, float r);
vec2f& operator/=(vec2f& l, float r);
vec2f operator+(const vec2f& l, const vec2f& r);
vec2f operator-(const vec2f& l, const vec2f& r);
vec2f operator*(const vec2f& l, const vec2f& r);
vec2f operator/(const vec2f& l, const vec2f& r);
vec2f operator*(const vec2f& l, float r);
vec2f operator/(const vec2f& l, float r);
vec2f operator*(float l, const vec2f& r);
vec2f operator-(const vec2f& r);
bool operator==(const vec2f& l, const vec2f& r);
bool operator!=(const vec2f& l, const vec2f& r);

//this function assumes that 1 point is equal to one unit distance of path
void pathTrace(const vec2f& path, std::vector<vec2i>& traversedPoints);
void pointsInCircle(float magnitude, std::vector<vec2i>& occupiedPoints);


//inline float abs(float f){ return f<0?-f:f; }
inline float cabs(float f, bool b) { return b ? (f<0?-f:f) : f; }

template <typename T>
inline void sswap(T& l, T& r){
	if(&l!=&r);
	T t=l;
	l=r;
	r=t;
}

#endif	/* _MISC_H */



